//
//  NetWorkRequestGroup.m
//  MXApp
//
//  Created by ChenChao on 15/1/15.
//  Copyright (c) 2015年 YingXiang. All rights reserved.
//

#import "NetWorkRequestGroup.h"
#import "NetWorkEngine.h"

@interface NetWorkRequestGroup ()
@property(strong, nonatomic) NSMutableDictionary* requests;

@end

@implementation NetWorkRequestGroup
- (id)init {
  self = [super init];
  if (self) {
    self.requests = [[NSMutableDictionary alloc] initWithCapacity:2];
  }
  return self;
}

- (void)dealloc {
  [self cancelAllRequest];
}

- (NSInteger)numberOfRequests {
  return [self.requests count];
}

- (void)removeOperation:(id)operation {
  NSArray* requestUrlArray = [self.requests allKeys];
  for (NSString* urlPath in requestUrlArray) {
    if (self.requests[urlPath] == operation) {
      [self.requests removeObjectForKey:urlPath];
      return;
    }
  }
}

- (void)addOperation:(id)operation urlPath:(NSString*)urlPath {
  if (urlPath && operation) {
    [self.requests setObject:operation forKey:urlPath];
  }
}

- (NSURLSessionTask*)findOperationByUrlPath:(NSString*)urlPath {
  if ([urlPath length] > 0) {
    return [self.requests objectForKey:urlPath];
  }
  return nil;
}

- (void)cancelRequestByUrlString:(NSString*)urlPath {
  if ([urlPath length] == 0) {
    return;
  }
  NSURLSessionTask* task = [self findOperationByUrlPath:urlPath];
  if (task) {
    [task cancel];
    [self.requests removeObjectForKey:urlPath];
  }
}

- (void)cancelRequestByNSURL:(NSURL*)nsUrl {
  NSString* urlString = [nsUrl absoluteString];
  [self cancelRequestByUrlString:urlString];
}

- (void)cancelRequestByOperation:(NSURLSessionTask*)operation {
  if (operation) {
    [operation cancel];
    [self removeOperation:operation];
  }
}

- (void)cancelAllRequest {
  NSArray* newRequests = [self.requests allValues];
  for (NSURLSessionTask* operation in newRequests) {
    [operation cancel];
  }
  [self.requests removeAllObjects];
}

- (NSURLSessionDataTask*)GET:(NSString*)URLString
                  parameters:(id)parameters
                     success:(void (^)(NSURLSessionDataTask* task, id responseObject))success
                     failure:(void (^)(NSURLSessionDataTask* task, NSError* error))failure {
  if ([URLString length] == 0) {
    return nil;
  }
  [self cancelRequestByUrlString:URLString];
  NSLog(@"URL:%@\n GET:%@\n", URLString, parameters);

  __weak __typeof(self) weakSelf = self;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wuninitialized"
  NSURLSessionDataTask* operation = [[NetWorkEngine sharedEngine] GET:URLString
      parameters:parameters
      progress:^(NSProgress* _Nonnull downloadProgress) {

      }
      success:^(NSURLSessionDataTask* _Nonnull task, id _Nullable responseObject) {
        NSLog(@"Response:%@\n", responseObject);
        __strong __typeof(weakSelf) strongSelf = weakSelf;
        [strongSelf removeOperation:operation];
        if (success) {
          success(task, responseObject);
        }
      }
      failure:^(NSURLSessionDataTask* _Nullable task, NSError* _Nonnull error) {
        __strong __typeof(weakSelf) strongSelf = weakSelf;
        [strongSelf removeOperation:operation];
        NSInteger errorCode = error.code;
#if DEBUG
        if (errorCode != NSURLErrorCancelled) {
          NSLog(@"cancelRequestByUser");
        }
#endif
        if (failure && (errorCode != NSURLErrorCancelled)) {
          failure(task, error);
        }
      }];
#pragma clang diagnostic pop

  [self addOperation:operation urlPath:URLString];
  return operation;
}

- (NSURLSessionDataTask*)POST:(NSString*)URLString
                   parameters:(id)parameters
                      success:(void (^)(NSURLSessionDataTask* task, id responseObject))success
                      failure:(void (^)(NSURLSessionDataTask* task, NSError* error))failure {
  if ([URLString length] == 0) {
    return nil;
  }
  [self cancelRequestByUrlString:URLString];
  __weak __typeof(self) weakSelf = self;
#if DEBUG
  NSLog(@"Header:%@", [NetWorkEngine sharedEngine].requestSerializer.HTTPRequestHeaders);
  NSLog(@"URL:%@\n POST:%@\n", URLString, parameters);
//    NSLog(@"Request-RequestHeader:%@\n",[MXNetEngine
//    sharedEngine].requestSerializer.HTTPRequestHeaders);
#endif

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wuninitialized"
  NSURLSessionDataTask* operation = [[NetWorkEngine sharedEngine] POST:URLString
      parameters:parameters
      progress:^(NSProgress* _Nonnull uploadProgress) {

      }
      success:^(NSURLSessionDataTask* _Nonnull task, id _Nullable responseObject) {
#if DEBUG
        NSLog(@"Response:%@\n", responseObject);
//                NSLog(@"Response-RequestHeader:%@\n",[MXNetEngine
//                sharedEngine].requestSerializer.HTTPRequestHeaders);
#endif
        __strong __typeof(weakSelf) strongSelf = weakSelf;
        [strongSelf removeOperation:operation];
        if (responseObject) {
          if (success) {
            success(task, responseObject);
          }
        } else {
          if (failure) {
            failure(task, nil);
          }
        }
      }
      failure:^(NSURLSessionDataTask* _Nullable task, NSError* _Nonnull error) {
        __strong __typeof(weakSelf) strongSelf = weakSelf;
        [strongSelf removeOperation:operation];
        NSInteger errorCode = error.code;
#if DEBUG
        NSLog(@"ERROR:%@", error);
        if (errorCode == NSURLErrorCancelled) {
          NSLog(@"cancelRequestByUser");
        }
#endif
        if (failure && (errorCode != NSURLErrorCancelled)) {
          failure(task, error);
        }
      }];
#pragma clang diagnostic pop

  [self addOperation:operation urlPath:URLString];
  return operation;
}

- (NSURLSessionDataTask*)POST:(NSString*)URLString
                   parameters:(id)parameters
    constructingBodyWithDatas:(NSArray*)bodyDatas
        constructingIdentifer:(NSString*)identifer
                      success:(void (^)(NSURLSessionDataTask* task, id responseObject))success
                      failure:(void (^)(NSURLSessionDataTask* task, NSError* error))failure {
  if ([URLString length] == 0) {
    return nil;
  }
  [self cancelRequestByUrlString:URLString];

  __weak __typeof(self) weakSelf = self;
#if DEBUG
  NSLog(@"Header:%@", [NetWorkEngine sharedEngine].requestSerializer.HTTPRequestHeaders);
  NSLog(@"URL:%@\n POST:%@\n", URLString, parameters);
//    NSLog(@"Request-RequestHeader:%@\n",[MXNetEngine
//    sharedEngine].requestSerializer.HTTPRequestHeaders);
#endif

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wuninitialized"
  NSURLSessionDataTask* operation = [[NetWorkEngine sharedEngine] POST:URLString
      parameters:parameters
      constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
        for (NSUInteger i = 0; i < [bodyDatas count]; i++) {
          [formData appendPartWithFileData:[bodyDatas objectAtIndex:i]
                                      name:identifer
                                  fileName:[NSString stringWithFormat:@"%@.png", identifer]
                                  mimeType:@"image/png"];
        }
      }
      progress:^(NSProgress* _Nonnull uploadProgress) {

      }
      success:^(NSURLSessionDataTask* _Nonnull task, id _Nullable responseObject) {
#if DEBUG
        NSLog(@"%@\n POST:%@", task.originalRequest, responseObject);
#endif
        __strong __typeof(weakSelf) strongSelf = weakSelf;
        [strongSelf removeOperation:operation];

        if (responseObject) {
          if (success) {
            success(task, responseObject);
          }
        } else {
          if (failure) {
            failure(task, nil);
          }
        }
      }
      failure:^(NSURLSessionDataTask* _Nullable task, NSError* _Nonnull error) {
        __strong __typeof(weakSelf) strongSelf = weakSelf;
        [strongSelf removeOperation:operation];
        NSInteger errorCode = error.code;
#if DEBUG
        NSLog(@"%@", error);
        if (errorCode == NSURLErrorCancelled) {
          NSLog(@"cancelRequestByUser");
        }
#endif
        if (failure && (errorCode != NSURLErrorCancelled)) {
          failure(task, error);
        }
      }];
#pragma clang diagnostic pop
  [self addOperation:operation urlPath:URLString];
  return operation;
}

@end
